﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators; 

namespace PSE.Framework.Service.Validation
{
    /// <summary>
    /// Classe para efetuar validações de intervalo
    /// </summary>
    internal class BvmfRangeValidator : Validator<IComparable>
    {

        /// <summary>
        /// Menor valor do intervalo
        /// </summary>
        private IComparable _lowBoundary;

        /// <summary>
        /// <Maior valor do intervalo
        /// </summary>
        private IComparable _highBoundary;

        /// <summary>
        /// Tipo de comparação (inclusive/exclusive) do menor valor do intervalo
        /// </summary>
        private RangeBoundaryType _lowBoundaryType;

        /// <summary>
        /// Tipo de comparação (inclusive/exclusive) do maior valor do intervalo
        /// </summary>
        private RangeBoundaryType _highBoundaryType;

        /// <summary>
        /// Construtor
        /// </summary>
        /// <param name="lowBoundary">Menor valor do intervalo</param>
        /// <param name="highBoundary">maior valor do intervalo</param>
        public BvmfRangeValidator(IComparable lowBoundary, IComparable highBoundary)
            : base(null, null)
        {
            _lowBoundary = lowBoundary;
            _highBoundary = highBoundary;
            _lowBoundaryType = RangeBoundaryType.Inclusive;
            _highBoundaryType = RangeBoundaryType.Inclusive;  
        }

        /// <summary>
        /// Construtor
        /// </summary>
        /// <param name="lowBoundary">Menor valor do intervalo</param>
        /// <param name="lowBoundaryType">Tipo de comparação (inclusive/exclusive) do menor valor do intervalo</param>
        /// <param name="highBoundary">maior valor do intervalo</param>
        /// <param name="highBoundaryType">Tipo de comparação (inclusive/exclusive) do maior valor do intervalo</param>
        public BvmfRangeValidator(IComparable lowBoundary, RangeBoundaryType lowBoundaryType, IComparable highBoundary, RangeBoundaryType highBoundaryType)
            : base(null, null)
        {
            _lowBoundary = lowBoundary;
            _highBoundary = highBoundary;
            _lowBoundaryType = lowBoundaryType;
            _highBoundaryType = highBoundaryType;
        }

        /// <summary>
        /// Método de implementação requerida (abstract na classe base) que contém a regra de validação 
        /// </summary>
        /// <param name="objectToValidate"></param>
        /// <param name="currentTarget"></param>
        /// <param name="key"></param>
        /// <param name="validationResults"></param>
        protected override void DoValidate(IComparable objectToValidate, object currentTarget, string key, ValidationResults validationResults)
        {
            if (objectToValidate == null)
            {
                validationResults.AddResult(new ValidationResult(this.MessageTemplate, currentTarget, key, this.Tag, this));
            }
            else
            {
                AdjustBoundaryTypes(objectToValidate);
                RangeValidator validator = new RangeValidator(_lowBoundary, _lowBoundaryType, _highBoundary, _highBoundaryType);
                validator.MessageTemplate = this.MessageTemplate;
                validator.Validate(objectToValidate, validationResults);
            }
        }

        /// <summary>
        /// Método responsável por efetuar o ajuste dos tipos que estão sendo comparados
        /// </summary>
        /// <param name="objectToValidate">Objeto que representa o item a ser validado</param>
        private void AdjustBoundaryTypes(IComparable objectToValidate)
        {
            if (_lowBoundary.GetType() != objectToValidate.GetType())
            {
                _lowBoundary = (IComparable) Convert.ChangeType(_lowBoundary, objectToValidate.GetType());
            }
            if (_highBoundary.GetType() != objectToValidate.GetType())
            {
                _highBoundary = (IComparable) Convert.ChangeType(_highBoundary, objectToValidate.GetType());
            }
        }

        /// <summary>
        /// Método de implementação requerida (abstract na classe base) e que retorna DefaultMessageTemplate
        /// </summary>
        protected override string DefaultMessageTemplate
        {
            get { return ""; }
        }
    }
}
